import {
  VuexModule,
  Module,
  Action,
  Mutation,
  getModule,
} from 'vuex-module-decorators';
import store from '@/store';
import { BillModule, BillType } from '@/store/modules/bill';
import { tagMap } from '@/utils/tagMap';
import { accountMap } from '@/utils/accountMap';
import { localStorageGet, localStorageSet } from '@/utils/localStorageUtil';
import { loaclDataMap } from '@/utils/loaclDataMap';
import http from '@/utils/http';
import { Toast } from 'vant';
import { tcbAuth, tcbDB } from '@/tcb';

// 定义预算类型，月 | 周 | 日
export enum EstimateType {
  Month,
  Week,
  Day,
}

// 定义资产账户接口类型
export interface IAssetAccount {
  accountId: number;
  name: string;
  tips: string;
  icon: string;
  color: string;
}

// 定义标签接口类型
export interface IBillTag {
  tagId: number;
  type: BillType;
  name: string;
  icon: string;
  color: string;
}

// 定义用户配置信息
export interface IUserConfig {
  createTime: number;
  assetAccountList: IAssetAccount[];
  billTagList: IBillTag[];
  estimate: {
    estimateType: EstimateType;
    estimateAmount: number;
  };
}

export interface IUserState {
  // 定义state接口类型
  userID: string;
  userConfig: IUserConfig;
  isLogin: boolean;
  isAddAssetAccountStatus: boolean;
  isAddBillTagStatus: boolean;
  currentActive: string;
}

// @Module 标记当前为module
// module本身有几种可以配置的属性
// 1、namespaced:boolean 启/停用 分模块
// 2、stateFactory:boolean 状态工厂
// 3、dynamic:boolean 在store创建之后，再添加到store中。 开启dynamic之后必须提供下面的属性
// 4、name:string 指定模块名称
// 5、store:Vuex.Store实体 提供初始的store
@Module({ dynamic: true, store, name: 'user' })
class User extends VuexModule implements IUserState {
  // 以下相当于state:{ ... }
  public userID = '';
  public isLogin = false;
  public userConfig: IUserConfig = {
    createTime: 0,
    billTagList: tagMap,
    assetAccountList: accountMap,
    estimate: {
      estimateType: EstimateType.Month,
      estimateAmount: 3000,
    },
  };
  public isAddAssetAccountStatus = false;
  public isAddBillTagStatus = false;
  public currentActive = 'asset';

  // @Mutation 标注为mutation
  @Mutation
  public initLocalUserConfig() {
    if (localStorageGet(loaclDataMap.userConfig)) {
      this.userConfig = localStorageGet(loaclDataMap.userConfig);
    } else {
      this.userConfig.createTime = new Date().getTime();
      this.userConfig.billTagList = tagMap;
      this.userConfig.assetAccountList = accountMap;
      localStorageSet(loaclDataMap.userConfig, this.userConfig);
    }
  }
  @Mutation
  public toggleIsLogin(isLogin: boolean) {
    this.isLogin = isLogin;
  }
  @Mutation
  public toggleUserID(userID: string) {
    this.userID = userID;
  }
  @Mutation
  public toggleIsAddAssetAccountStatus(isAddAssetAccountStatus: boolean) {
    this.isAddAssetAccountStatus = isAddAssetAccountStatus;
  }
  @Mutation
  public toggleIsAddBillTagStatus(isAddBillTagStatus: boolean) {
    this.isAddBillTagStatus = isAddBillTagStatus;
  }
  @Mutation
  public toggleCurrentActive(currentActive: string) {
    this.currentActive = currentActive;
  }
  @Mutation
  public updateUserConfig(userConfig: IUserConfig) {
    this.userConfig = userConfig;
  }

  @Action
  public async init() {
    if (!this.isLogin) {
      this.initLocalUserConfig();
      BillModule.resetBills(localStorageGet(loaclDataMap.bills) || []);
      BillModule.updateBillSummary();
    } else {
      this.loginSuccess(this.userID);
    }
  }
  @Action
  public async login(userID: string) {
    http.getTcbTicket(
      JSON.stringify({ userID }),
    ).then((tcbTicket: string) => {
      this.tcbLogin({userID, tcbTicket});
    }).catch(() => {
      Toast.fail({
        message: '云开发鉴权获取失败，请联系作者修复！微信号：LeeYu2333',
        forbidClick: true,
        duration: 2000,
      });
    });
  }
  @Action
  public async tcbLogin(loginOptions: { userID: string, tcbTicket: string }) {
    const loginState = tcbAuth.hasLoginState();
    if (!loginState) {
      tcbAuth.customAuthProvider().signIn(loginOptions.tcbTicket).then(() => {
        this.loginSuccess(loginOptions.userID);
      }).catch((err) => {
        Toast.fail('登录失败' + err);
      });
    } else {
      this.loginSuccess(loginOptions.userID);
    }
  }
  @Action
  public async logout() {
    const loginState = tcbAuth.hasLoginState();
    if (!loginState) {
      tcbAuth.signOut().then(() => {
        this.logoutSuccess();
      }).catch((error) => {
        Toast.fail('登出失败' + error);
      });
    } else {
      this.logoutSuccess();
    }
  }
  @Action
  public async getUserConfig(userID: string) {
    tcbDB.collection('bill_userconfig').where({
      userID,
    }).get().then((res) => {
      if (res.data.length === 0) {
        this.userConfig.createTime = new Date().getTime();
        this.userConfig.billTagList = tagMap;
        this.userConfig.assetAccountList = accountMap;
        this.addUserConfig(this.userConfig);
      } else {
        this.updateUserConfig(res.data[0].userConfig);
      }
    }).catch(() => {
      Toast.fail('获取用户配置失败');
    });
  }
  @Action
  public async addUserConfig(userConfig: IUserConfig) {
    tcbDB.collection('bill_userconfig').add({userID: this.userID, userConfig}).catch(() => {
      Toast.fail('初始化失败');
    });
  }
  @Action
  public async editUserConfig(userConfig: IUserConfig) {
    tcbDB.collection('bill_userconfig').where({
      userID: this.userID,
    }).update({userID: this.userID, userConfig}).catch(() => {
      Toast.fail('编辑失败');
    });
  }
  @Action
  public addAssetAccount(assetAccount: IAssetAccount) {
    const userConfig = this.userConfig;
    userConfig.assetAccountList.push(assetAccount);
    if (!this.isLogin) {
      localStorageSet(loaclDataMap.userConfig, this.userConfig);
    } else {
      this.editUserConfig(userConfig);
    }
    this.updateUserConfig(userConfig);
  }
  @Action
  public addBillTag(billTag: IBillTag) {
    const userConfig = this.userConfig;
    this.userConfig.billTagList.push(billTag);
    if (!this.isLogin) {
      localStorageSet(loaclDataMap.userConfig, this.userConfig);
    } else {
      this.editUserConfig(userConfig);
    }
    this.updateUserConfig(userConfig);
  }
  @Action
  private async loginSuccess(userID: string) {
    Toast.success('登录成功');
    this.toggleIsLogin(true);
    this.toggleUserID(userID);
    this.getUserConfig(userID);
    BillModule.getBills(userID);
  }
  @Action
  private async logoutSuccess() {
    this.toggleIsLogin(false);
    this.toggleUserID('');
    this.init();
    Toast.success('登出成功');
  }
}

export const UserModule = getModule(User);
